/*
 * Copyright (c) 2022-2023 cetcclout Co., Ltd All rights reserved.
 * Sensor Adapter is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.cetccloud.cimp.adapter.protocol;

import cn.hutool.json.JSONUtil;

import com.cetccloud.cimp.adapter.datasource.sqldb.vo.ServerConfig;
import com.cetccloud.cimp.adapter.handler.abstracts.*;
import com.cetccloud.cimp.adapter.handler.mqtt.MqttAuthHandler;
import com.cetccloud.cimp.adapter.handler.mqtt.MqttCheckHandler;
import com.cetccloud.cimp.adapter.handler.mqtt.MqttParserHandler;
import com.cetccloud.cimp.adapter.handler.netty.TcpAuthHandler;
import com.cetccloud.cimp.adapter.handler.netty.TcpCheckHandler;
import com.cetccloud.cimp.adapter.handler.netty.TcpParserHandler;
import com.cetccloud.cimp.adapter.protocol.chain.DefaultDataChain;
import com.cetccloud.cimp.adapter.server.mqtt.MqttServer;
import com.cetccloud.cimp.adapter.server.netty.NettyServer;
import com.cetccloud.cimp.adapter.util.SpringAppContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

/**
 * @author
 * @apiNote 通信服务选择器
 * @date 2022/12/30 16:50
 */
public interface ProtocolExecutor extends ToDtuHandler{


    /**
     * 初始化服务信息
     */
    static ProtocolExecutor init(String serverType, ServerConfig serverConfig) {
        String[] handler = serverConfig.getDoLinkList().toArray(new String[0]);
        if(null != handler){
            if(handler.length == 3){
                return init3(serverType, serverConfig, handler);
            }else {
                return defaultInit(serverConfig);
            }
        }else {
            return null;
        }
    }

    /**
     * 默认服务和执行链路，建立端口的监听/连接，配置消息侦听器
     */
    static ProtocolExecutor defaultInit(ServerConfig serverConfig) {

        //初始化处理链路业务！
        DefaultDataChain defaultDataChain = SpringAppContextUtil.getBean(DefaultDataChain.class);

        AbstractAuthHandler authHandler = null;
        AbstractParserHandler parserHandler = null;
        AbstractCheckHandler checkHandler = null;
        switch (serverConfig.getServerType()){
            case "MQTT":{
                //MQTT服务接入方式,默认处理链初始化
                authHandler = SpringAppContextUtil.getBean(MqttAuthHandler.class);
                parserHandler = SpringAppContextUtil.getBean(MqttParserHandler.class);
                checkHandler = SpringAppContextUtil.getBean(MqttCheckHandler.class);
            }break;
            case "TCP":{
                //TCP服务接入方式,默认处理链初始化
                authHandler = SpringAppContextUtil.getBean(TcpAuthHandler.class);
                parserHandler = SpringAppContextUtil.getBean(TcpParserHandler.class);
                checkHandler = SpringAppContextUtil.getBean(TcpCheckHandler.class);
            }break;
            default:{
                throw new RuntimeException("未知的接入服务类型！！");
            }
        }
        
        //打开对应的服务
        ProtocolExecutor protocolExecutor = getDefaultInstance(defaultDataChain,serverConfig.getServerType());
        defaultDataChain.makeDataChain(authHandler,parserHandler,checkHandler,protocolExecutor);
        protocolExecutor.start(serverConfig);

        return protocolExecutor;
    }
    
    /**
     * 适配初始化三个服务配置
     */
    static ProtocolExecutor init3(String serverType, ServerConfig serverConfig, String... handler) {
        try {
            //从Spring创建对象实例
            Object authHandlerObject = SpringAppContextUtil.getBean(handler[0]);
            Object parserHandlerObject = SpringAppContextUtil.getBean(handler[1]);
            Object checkHandlerObject = SpringAppContextUtil.getBean(handler[2]);

            if(!(authHandlerObject instanceof AbstractAuthHandler)){
                //todo 对象类型错误抛出异常信息或者返回错误信息
                return null;
            }
            if(!(parserHandlerObject instanceof AbstractParserHandler)){
                //todo 对象类型错误抛出异常信息或者返回错误信息
                return null;
            }
            if(!(checkHandlerObject instanceof AbstractCheckHandler)){
                //todo 对象类型错误抛出异常信息或者返回错误信息
                return null;
            }


            AbstractAuthHandler abstractAuthHandler = (AbstractAuthHandler) authHandlerObject;

            AbstractParserHandler abstractParserHandler = (AbstractParserHandler) parserHandlerObject;
            //加载配置参数
            abstractParserHandler.init(JSONUtil.parseObj(serverConfig.getParams()).getStr(serverConfig.getLinksList().get(1)));

            AbstractCheckHandler abstractCheckHandler = (AbstractCheckHandler) checkHandlerObject;

            //初始化处理链路业务！
            DefaultDataChain defaultDataChain = SpringAppContextUtil.getBean(DefaultDataChain.class);

            //获取服务对象打开对应的服务
            ProtocolExecutor protocolExecutor = getDefaultInstance(defaultDataChain,serverType);
            defaultDataChain.makeDataChain(abstractAuthHandler, abstractParserHandler, abstractCheckHandler, protocolExecutor);
            protocolExecutor.start(serverConfig);

            return  protocolExecutor;
        } catch (NoSuchBeanDefinitionException e) {
            e.printStackTrace();
            throw new RuntimeException("对象创建异常：："+ e);
        }
    }

    /**
     * 加载初始化默认的通信服务（Netty）
     */
    static ProtocolExecutor getDefaultInstance(DefaultDataChain dataChain, String serverType) {
        serverType = StringUtils.isEmpty(serverType)?"TCP":serverType;
        switch (serverType){
            case "MQTT":{
                //MQTT服务接入方式
                return new MqttServer(dataChain);
            }
            case "TCP":{
                //TCP服务接入方式
                return new NettyServer(dataChain);
            }
            default:{
                throw new RuntimeException("未知的接入服务类型！！");
            }
        }
    }

    /**
     * 获取信息处理操作集
     */
    DefaultDataChain getDefaultDataChain();

    /**
     * 绑定端口启动服务
     */
    void start(ServerConfig serverConfig);

    /**
     * 退出服务
     */
    void quit();

}
